import cv2
import numpy as np
import EView as ev 
# 打开摄像头


Peri = ev.Peripheral()
# 设置波特率
Peri.uartInit(115200)
Peri.sendUartData("The serial port is initialized\r")

# 2. 摄像头初始化
Peri.sendUartData("The camera starts to initialize\r")
# * 创建一个摄像头捕获对象
Cap = cv2.VideoCapture(0)
if not Cap.isOpened():
    Peri.sendUartData("The Camera 0 failed to open\r")
    Cap = cv2.VideoCapture(1)
if not Cap.isOpened():
    Peri.sendUartData("The Camera 1 failed to open\r")
    Cap = cv2.VideoCapture(2)
if not Cap.isOpened():
    Peri.sendUartData("The Camera 2 failed to open\r")
    Cap = cv2.VideoCapture(3)
if not Cap.isOpened():
    Peri.sendUartData("The Camera 3 failed to open\r")
    Cap = cv2.VideoCapture(4)
if not Cap.isOpened():
    Peri.sendUartData("The Camera 4 failed to open\r")
    exit()

# 摄像头读取测试
ret, frame = Cap.read()
# 如果正确读取帧，ret为True
if not ret:
    Peri.sendUartData("The camera initialization failed\r")
    exit()
Peri.sendUartData("The camera is initialized\r")

cap = Cap

cv2.namedWindow('camera', cv2.WINDOW_AUTOSIZE)
# 检查是否打开正确
while cap.isOpened():
    open_flag , frame1 = cap.read()
    frame = cv2.flip(frame1, 1)
    print(open_flag)
    print(frame1)
    if open_flag:
        if frame is not None:
            lower_red1 = np.array([0, 60, 60])
            upper_red1 = np.array([8, 255, 255])

            lower_red2 = np.array([160, 60, 60])
            upper_red2 = np.array([180, 255, 255])

            # 通过cv2.bitwise_or合并两个范围
            lower_red_union = cv2.bitwise_or(lower_red1, lower_red2)
            upper_red_union = cv2.bitwise_or(upper_red1, upper_red2)

            # 创建红色的HSV范围
            red_hsv_union = {'Lower': lower_red_union, 'Upper': upper_red_union}

            ball_color = 'red'

            color_dist = {'red': red_hsv_union,
                          'blue': {'Lower': np.array([100, 80, 46]), 'Upper': np.array([124, 255, 255])},
                          'green': {'Lower': np.array([60, 50, 50]), 'Upper': np.array([120, 255, 255])},
                          }

            #frame = cv2.imread('redpoint4.jpg')
            #cv2.imshow('redpoint', frame)

            # 高斯模糊
            gs_frame = cv2.GaussianBlur(frame, (5, 5), 0)
            # cv2.imshow('gs_frame', gs_frame)

            # 转化成HSV图像
            hsv = cv2.cvtColor(gs_frame, cv2.COLOR_BGR2HSV)
            # cv2.imshow('hsv', hsv)

            # 去除阈值外颜色
            inRange_hsv = cv2.inRange(hsv, color_dist[ball_color]['Lower'], color_dist[ball_color]['Upper'])
            #cv2.imshow('inRange_hsv', inRange_hsv)

            # 腐蚀,膨胀
            kernel = np.ones((4, 4), np.uint8)
            kernel1 = np.ones((5, 5), np.uint8)
            kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (4, 4))

            erode_hsv = cv2.erode(inRange_hsv, kernel1, iterations=1)
            #cv2.imshow('erode_hsv', erode_hsv)
            dilation = cv2.dilate(erode_hsv, kernel1, iterations=2)
            #cv2.imshow('dilation', dilation)

            # 叠加观察
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            res = cv2.addWeighted(gray, 0.8, erode_hsv, 0.2, 0)  # 猫占0.4权重，狗占0.6权重
            #cv2.imshow('res', res)
            '''
            # 外轮廓
            cnts = cv2.findContours(erode_hsv.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
            c = max(cnts, key=cv2.contourArea)
            rect = cv2.minAreaRect(c)
            box = cv2.boxPoints(rect)
            # 在原始图像上标记外部轮廓与矩形框
            cv2.drawContours(frame, [np.intp(box)], -1, (0, 0, 255), 2)
            cv2.drawContours(frame, [c], -1, (0, 0, 255), 2)
            #cv2.imshow('EXTERNAL', frame)
            '''

            '''
            # 内轮廓（包括内部轮廓）
            contours, hierarchy = cv2.findContours(dilation.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
            #internal_contour = contours[0]
            # 遍历轮廓和层次结构
            for i in range(len(contours)):
                # 如果当前轮廓没有子轮廓，说明是内部轮廓
                if hierarchy[0][i][2] == -1:
                    internal_contour = contours[i]
                    # 在原始图像上标记内部轮廓与矩形框
                    rect = cv2.minAreaRect(internal_contour)
                    box = cv2.boxPoints(rect)
                    cv2.drawContours(frame, [np.intp(box)], -1, (0, 255, 255), 2)
                    cv2.drawContours(frame, [internal_contour], -1, (255, 0, 0), 2)


                    # 矩形框中心坐标
                    center_x = int((box[0][0] + box[2][0]) / 2)
                    center_y = int((box[0][1] + box[2][1]) / 2)
                    centers = [center_x, center_y]
                    # 打印矩形框中心坐标
                    print("Center of Contour Box:", centers)
            '''
            # 查找轮廓
            contours, hierarchy = cv2.findContours(dilation.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

            # 初始化最小轮廓面积和对应的轮廓索引
            min_contour_area = float('inf')
            min_contour_index = -1

            # 遍历所有轮廓
            for i, contour in enumerate(contours):
                # 计算当前轮廓的面积
                area = cv2.contourArea(contour)

                # 更新最小轮廓面积和对应的轮廓索引
                if area < min_contour_area:
                    min_contour_area = area
                    min_contour_index = i

            # 如果找到最小轮廓，进行处理
            if min_contour_index != -1:
                min_contour = contours[min_contour_index]
                rect = cv2.minAreaRect(min_contour)
                box = cv2.boxPoints(rect)
                cv2.drawContours(frame, [np.intp(box)], -1, (0, 255, 255), 2)
                cv2.drawContours(frame, [min_contour], -1, (255, 0, 0), 2)
                center_x = int((box[0][0] + box[2][0]) / 2)
                center_y = int((box[0][1] + box[2][1]) / 2)
                centers = [center_x, center_y]
                print("Center of Contour Box:", centers)

            # 显示结果
            cv2.imshow('camera', frame)

            if cv2.waitKey(100) & 0xFF == ord('q'):
                break
        else:
            print("无画面")
    else:
        print("无法读取摄像头！")

cap.release()
cv2.destroyAllWindows()